import pyautogui
import time
import cv2
import numpy as np
import pygetwindow as gw
from pynput import keyboard
import os

# 控制自动打怪的开关
auto_fight_enabled = False

# 处理按键事件
def on_press(key):
    global auto_fight_enabled
    try:
        if key == keyboard.Key.f3:
            auto_fight_enabled = not auto_fight_enabled
            if auto_fight_enabled:
                print("自动打怪已开启")
            else:
                print("自动打怪已停止")
    except AttributeError:
        pass

# 启动监听键盘事件的线程
listener = keyboard.Listener(on_press=on_press)
listener.start()

# 模拟按 Tab 键选中怪物
def select_monster():
    pyautogui.press('tab')
    print("按下 Tab 键尝试选中怪物")

# 进行法术攻击
def spell_attack():
    pyautogui.press('3')
    print("执行法术攻击，按下 3 键")

# 进行物理攻击
def physical_attack():
    # 这里假设物理攻击快捷键为 2，可按需修改
    pyautogui.press('2')
    print("执行物理攻击，按下 2 键")

# 查找血条位置
def find_health_bar(template_path):
    # 检查文件是否存在
    if not os.path.exists(template_path):
        print(f"模板图片文件不存在: {template_path}")
        return None
    # 截取屏幕
    screenshot = pyautogui.screenshot()
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    # 读取模板图片
    template = cv2.imread(template_path, cv2.IMREAD_COLOR)
    if template is None:
        print(f"无法读取模板图片: {template_path}")
        return None
    h, w = template.shape[:2]
    # 进行模板匹配，使用 TM_SQDIFF_NORMED 方法
    result = cv2.matchTemplate(screenshot, template, cv2.TM_SQDIFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    # TM_SQDIFF_NORMED 方法中，最小值代表最佳匹配
    top_left = min_loc
    # 设置匹配阈值
    threshold = 0.1
    print(f"血条匹配最小值: {min_val}，阈值: {threshold}")
    if min_val > threshold:
        print("未找到匹配的血条")
        return None
    # 计算血条区域
    health_bar_region = (top_left[0], top_left[1], w, h)
    print("找到匹配的血条")
    return health_bar_region

# 获取角色血量百分比
def get_health_percentage(template_path):
    # 查找血条位置
    health_bar_region = find_health_bar(template_path)
    if health_bar_region is None:
        return 0
    left, top, width, height = health_bar_region
    # 截取血条区域
    screenshot = pyautogui.screenshot(region=health_bar_region)
    screenshot = np.array(screenshot)
    screenshot = cv2.cvtColor(screenshot, cv2.COLOR_RGB2BGR)

    # 转换到 HSV 颜色空间，方便识别红色
    hsv = cv2.cvtColor(screenshot, cv2.COLOR_BGR2HSV)

    # 定义红色的 HSV 范围，红色在 HSV 空间中不连续，需要两个范围
    lower_red1 = np.array([0, 100, 100])
    upper_red1 = np.array([10, 255, 255])
    lower_red2 = np.array([160, 100, 100])
    upper_red2 = np.array([180, 255, 255])

    # 创建掩码
    mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
    mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
    mask = cv2.bitwise_or(mask1, mask2)

    # 形态学操作，去除噪声
    kernel = np.ones((3, 3), np.uint8)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

    # 计算红色像素的数量
    red_pixels = cv2.countNonZero(mask)
    total_pixels = width * height

    # 计算血量百分比
    health_percentage = (red_pixels / total_pixels) * 100
    print(f"当前血量百分比: {health_percentage}%")
    return health_percentage

# 加血操作
def heal():
    pyautogui.press('5')
    print("按下 5 键加血")

# 拾取掉落物品
def pick_up_items():
    pyautogui.press('`')
    print("按下 ` 键拾取物品")

# 角色在一定范围内跑动寻找怪物
def move_character_to_find_monster(template_path):
    screen_width, screen_height = pyautogui.size()
    center_x, center_y = screen_width // 2, screen_height // 2
    directions = [
        (center_x, center_y - 500),  # 上
        (center_x, center_y + 500),  # 下
        (center_x - 500, center_y),  # 左
        (center_x + 500, center_y)   # 右
    ]
    for x, y in directions:
        if x < 0:
            x = 0
        if x >= screen_width:
            x = screen_width - 1
        if y < 0:
            y = 0
        if y >= screen_height:
            y = screen_height - 1
        pyautogui.click(x, y)
        print(f"点击坐标 ({x}, {y}) 移动角色")
        time.sleep(2)  # 等待角色移动
        select_monster()
        if not is_monster_dead(template_path):
            return True
    return False

# 判断怪物是否死亡
def is_monster_dead(template_path):
    health_bar_region = find_health_bar(template_path)
    is_dead = health_bar_region is None
    print(f"怪物是否死亡: {is_dead}")
    return is_dead

# 判断是否在游戏窗口
def is_in_game_window():
    try:
        active_window = gw.getActiveWindow()
        if active_window and "大唐无双" in active_window.title:
            print("当前在游戏窗口")
            return True
    except Exception as e:
        print(f"获取窗口信息出错: {e}")
    print("当前不在游戏窗口")
    return False

# 自动打怪主循环
def auto_fight(template_path):
    global auto_fight_enabled
    last_health_check_time = time.time()
    last_key_5_press_time = time.time()
    last_key_4_press_time = time.time()

    while True:
        if not auto_fight_enabled:
            time.sleep(0.1)
            continue

        if not is_in_game_window():
            time.sleep(1)  # 若不在游戏窗口，暂停 1 秒后再次检查
            continue

        select_monster()
        if not is_monster_dead(template_path):
            print("已选中怪物，开始攻击")
            # 若选中怪物，开始攻击
            while True:
                if not auto_fight_enabled or not is_in_game_window():
                    break

                # 法术攻击 15 秒
                spell_attack_start_time = time.time()
                while time.time() - spell_attack_start_time < 15:
                    if not auto_fight_enabled or not is_in_game_window():
                        break

                    # 每隔 5 秒检测一次血条情况
                    if time.time() - last_health_check_time >= 5:
                        health_percentage = get_health_percentage(template_path)
                        last_health_check_time = time.time()

                    # 每隔 10 秒按一次 5 键
                    if time.time() - last_key_5_press_time >= 10:
                        heal()
                        last_key_5_press_time = time.time()

                    # 每隔 20 秒按一次 4 键
                    if time.time() - last_key_4_press_time >= 20:
                        pyautogui.press('4')
                        print("按下 4 键")
                        last_key_4_press_time = time.time()

                    spell_attack()

                    if is_monster_dead(template_path):
                        pick_up_items()
                        break
                    time.sleep(1)

                if is_monster_dead(template_path):
                    break

                # 按 5 键加血
                heal()

                # 物理攻击 10 秒
                physical_attack_start_time = time.time()
                while time.time() - physical_attack_start_time < 10:
                    if not auto_fight_enabled or not is_in_game_window():
                        break

                    # 每隔 5 秒检测一次血条情况
                    if time.time() - last_health_check_time >= 5:
                        health_percentage = get_health_percentage(template_path)
                        last_health_check_time = time.time()

                    # 每隔 10 秒按一次 5 键
                    if time.time() - last_key_5_press_time >= 10:
                        heal()
                        last_key_5_press_time = time.time()

                    # 每隔 20 秒按一次 4 键
                    if time.time() - last_key_4_press_time >= 20:
                        pyautogui.press('4')
                        print("按下 4 键")
                        last_key_4_press_time = time.time()

                    physical_attack()

                    if is_monster_dead(template_path):
                        pick_up_items()
                        break
                    time.sleep(1)

                if is_monster_dead(template_path):
                    break

                # 按 2 键
                pyautogui.press('2')
                print("按下 2 键")
        else:
            print("未选中怪物，开始跑动寻找")
            # 若未选中怪物，开始跑动寻找
            if not move_character_to_find_monster(template_path):
                continue

if __name__ == "__main__":
    # 安装必要库
    try:
        import pygetwindow as gw
        from pynput import keyboard
    except ImportError:
        print("缺少必要库，正在尝试安装...")
        import subprocess
        try:
            subprocess.check_call(["pip", "install", "pygetwindow", "pynput"])
            import pygetwindow as gw
            from pynput import keyboard
            print("必要库安装成功")
        except Exception as e:
            print(f"安装必要库失败: {e}")
            exit(1)

    # 血条模板图片路径，修改为实际的绝对路径
    template_path = "your_actual_absolute_path/health_bar_template.png"
    if os.path.exists(template_path):
        print("图片文件存在，开始运行程序")
    else:
        print("图片文件不存在，请检查路径，程序退出")
        exit(1)

    # 给一些准备时间，方便切换到游戏窗口
    time.sleep(5)
    auto_fight(template_path)